﻿
Imports System.Timers
Imports locks

Partial Public Class eventComb
    Private Function _waitfor(ByVal ec As eventComb, ByVal begin As _do(Of Boolean)) As Boolean
        assert(Not begin Is Nothing)
        assert_in_lock()
        If Not ec Is Nothing AndAlso object_compare(Me, ec) <> 0 AndAlso ec.not_started() Then
            inc_pends()
            ec.cb = Me
            Return begin()
        Else
            Return False
        End If
    End Function

    Private Function _waitfor(ByVal ec As eventComb, ByVal timeoutMs As Int64) As Boolean
        Return _waitfor(ec,
                        Function() As Boolean
                            Return begin(ec, timeoutMs)
                        End Function)
    End Function

    Private Function _waitfor(ByVal ec As eventComb) As Boolean
        Return _waitfor(ec,
                        Function() As Boolean
                            Return begin(ec)
                        End Function)
    End Function

    Private Function _waitfor(ByVal ecs() As eventComb) As Boolean
        assert_in_lock()
        If ecs Is Nothing OrElse ecs.Length() = 0 Then
            Return False
        Else
            For i As Int64 = 0 To ecs.Length() - 1
                If Not _waitfor(ecs(i)) Then
                    Return False
                End If
            Next

            Return True
        End If
    End Function

    Private Function _waitone(ByVal ecs() As eventComb) As Boolean
        assert_in_lock()
        If _waitfor(ecs) Then
            assert(Not ecs Is Nothing AndAlso ecs.Length() > 0)
            For i As Int64 = 1 To ecs.Length() - 1
                dec_pends()
            Next
            Return True
        Else
            Return False
        End If
    End Function

    Private Function _waitfor(ByVal [try] As _do(Of Boolean), ByVal w As _do(Of callbackAction, Boolean)) As Boolean
        assert(Not w Is Nothing)
        If [try] Is Nothing Then
            Return False
        Else
            Return w(New callbackAction(check:=[try]))
        End If
    End Function

    Private Function _waitfor(ByVal [try] As _do(Of Boolean), ByVal timeoutMs As Int32) As Boolean
        Return _waitfor([try], Function(ByRef x) _waitfor(x, timeoutMs))
    End Function

    Private Function _waitfor(ByVal [try] As _do(Of Boolean)) As Boolean
        Return _waitfor([try], Function(ByRef x) _waitfor(x))
    End Function

    Private Function _waitfor(ByRef cb As void) As Boolean
        assert_in_lock()
        inc_pends()
        cb = Sub()
                 [resume](Me)
             End Sub
        Return True
    End Function

    Private Function _waitfor(ByVal action As callbackAction, ByVal check As _do(Of Boolean)) As Boolean
        assert(Not check Is Nothing)
        If action Is Nothing Then
            Return False
        Else
            Dim cb As void = Nothing
            If Not _waitfor(cb) Then
                Return False
            Else
                assert(Not cb Is Nothing)
                Return begin(action) AndAlso
                       begin(New callbackAction(check:=check,
                                                end:=Function() true_(cb)))
            End If
        End If
    End Function

    Private Function _waitfor(ByVal action As callbackAction, ByVal timeoutMs As Int32) As Boolean
        Dim startMs As Int64 = 0
        startMs = Now.milliseconds()
        Return _waitfor(action, Function() As Boolean
                                    If Now.milliseconds() - startMs >= timeoutMs Then
                                        Return callbackAction.check_pass
                                    Else
                                        Return callbackAction.action_check(action)()
                                    End If
                                End Function)
    End Function

    Private Function _waitfor(ByVal action As callbackAction) As Boolean
        Return _waitfor(action, callbackAction.action_check(action))
    End Function

    Private Function _waitfor(ByVal ms As Int64) As Boolean
        If ms < 0 Then
            Return False
        ElseIf ms = 0 Then
            Return True
        Else
            Dim d As void = Nothing
            If _waitfor(d) Then
                assert(Not stopwatch.push(ms, d) Is Nothing)
                Return True
            Else
                Return False
            End If
        End If
    End Function

    Private Function _waitfor(ByVal l As lockWrapper(Of eventCombLock)) As Boolean
        If l Is Nothing Then
            Return False
        Else
            l.wait()
            Return True
        End If
    End Function

    Private Function _waitfor(Of T)(ByVal l As multilock(Of eventCombLock), ByVal i As T) As Boolean
        l.lock(i)
        Return True
    End Function

    Public Shared Function waitfor(ByVal ec As eventComb, ByVal timeoutMs As Int64) As Boolean
        Return current()._waitfor(ec, timeoutMs)
    End Function

    Public Shared Function waitfor(ByVal ec As eventComb) As Boolean
        Return current()._waitfor(ec)
    End Function

    Public Shared Function waitfor(ByVal ParamArray ecs() As eventComb) As Boolean
        Return current()._waitfor(ecs)
    End Function

    Public Shared Function waitone(ByVal ParamArray ecs() As eventComb) As Boolean
        Return current()._waitone(ecs)
    End Function

    Public Shared Function waitfor(ByVal action As callbackAction, ByVal timeoutMs As Int32) As Boolean
        Return current()._waitfor(action, timeoutMs)
    End Function

    Public Shared Function waitfor(ByVal action As callbackAction) As Boolean
        Return current()._waitfor(action)
    End Function

    Public Shared Function waitfor(ByVal [try] As _do(Of Boolean), ByVal timeoutMs As Int32) As Boolean
        Return current()._waitfor([try], timeoutMs)
    End Function

    Public Shared Function waitfor(ByVal [try] As _do(Of Boolean)) As Boolean
        Return current()._waitfor([try])
    End Function

    Public Shared Function waitfor(ByRef cb As void) As Boolean
        Return current()._waitfor(cb)
    End Function

    Public Shared Function waitfor(ByVal ms As Int64) As Boolean
        Return current()._waitfor(ms)
    End Function

    Public Shared Function waitfor(ByVal l As lockWrapper(Of eventCombLock)) As Boolean
        Return current()._waitfor(l)
    End Function

    Public Shared Function waitfor(Of T)(ByVal l As multilock(Of eventCombLock), ByVal i As T) As Boolean
        Return current()._waitfor(l, i)
    End Function
End Class
